#include "stdafx.h"

#include "Engine.h"

bool bPreciseMeasuring;


TimerRecord timerRec[T_MAX_TIMER];
wchar_t watchNames[T_MAX_TIMER][MAX_TIMER_NAME];

void (*TimerPrint)(wchar_t* szMessage);
void (*TimerPrintSave)(wchar_t* szMessage);

uint64 uiFrequency;

void TestPreciseMeasuring()
{
	LARGE_INTEGER ui;
	bPreciseMeasuring = true;
	
	if(::QueryPerformanceFrequency(&ui) == FALSE)
	{
		bPreciseMeasuring = false;
		uiFrequency = 1;
		return;
	}

	uiFrequency = ui.QuadPart / 1024;
}

void InitTimerNames()
{
	wcscpy_s(watchNames[0], MAX_TIMER_NAME, T_BIT_GENERATOR_NAME);
	wcscpy_s(watchNames[1], MAX_TIMER_NAME, T_DB_UNKNOWN_NAME);
	wcscpy_s(watchNames[2], MAX_TIMER_NAME, T_DB_SET_IMPOSSIBLE_NAME);
	wcscpy_s(watchNames[3], MAX_TIMER_NAME, T_DB_CAPTURES_NAME);
	wcscpy_s(watchNames[4], MAX_TIMER_NAME, T_DB_PASS_WHITE_NAME);
	wcscpy_s(watchNames[5], MAX_TIMER_NAME, T_DB_PASS_BLACK_NAME);
	wcscpy_s(watchNames[6], MAX_TIMER_NAME, T_DB_PROPAGATE_WHITE_NAME);
	wcscpy_s(watchNames[7], MAX_TIMER_NAME, T_DB_PROPAGATE_BLACK_NAME);
	wcscpy_s(watchNames[8], MAX_TIMER_NAME, T_DB_UNKNOWN_TO_DRAW_NAME);
	wcscpy_s(watchNames[9], MAX_TIMER_NAME, T_TEST_JUMP_NAME);
	wcscpy_s(watchNames[10], MAX_TIMER_NAME, T_FILE_READ_NAME);
	wcscpy_s(watchNames[11], MAX_TIMER_NAME, T_FILE_WRITE_NAME);
}

void InitTimer()
{
	memset(timerRec, 0, sizeof(TimerRecord)*T_MAX_TIMER);

	InitTimerNames();
	TestPreciseMeasuring();
}

uint64 inline GetTime()
{
	if(bPreciseMeasuring)
	{
		LARGE_INTEGER li;
		::QueryPerformanceCounter(&li);
		return li.QuadPart;
	}
	else
		return (uint64)::GetTickCount64();
}

void WatchStart(int type)
{
	timerRec[type].iStartCallCount++;
	if(timerRec[type].iStartCallCount == 1)
	{
		timerRec[type].uiStartTime = GetTime();
	}
}

void WatchEnd(int type)
{
	timerRec[type].iStartCallCount--;
	if(timerRec[type].iStartCallCount == 0)
	{
		timerRec[type].iNumPasses++;
		timerRec[type].uiTotalTime += GetTime() - timerRec[type].uiStartTime;
		timerRec[type].uiStartTime = 0;
		timerRec[type].uiAverageTime = timerRec[type].uiTotalTime / timerRec[type].iNumPasses;
	}

}

wchar_t szTimerMessage[1000];

void PrintTimerOutput()
{
	if(TimerPrint == NULL)
		return;

	for(int i = 0; i < T_MAX_TIMER; i++)
	{
		swprintf_s(szTimerMessage, 500, L"%s: Avg: %llu ms, Total: %llu ms\n", watchNames[i], timerRec[i].uiAverageTime / uiFrequency, timerRec[i].uiTotalTime / uiFrequency);
		TimerPrint(szTimerMessage);
	}
}

int iTimerLogId;

void LogPrintMessageCallback(wchar_t* szMessage)
{
	LogMessage(iTimerLogId, szMessage);
}

void LogTimerOutput(char *szFile)
{
	iTimerLogId = LogInit(szFile);

	TimerPrintSave = TimerPrint;
	TimerPrint = LogPrintMessageCallback;

	PrintTimerOutput();

	TimerPrint = TimerPrintSave;

	LogClose(iTimerLogId);
}
